package breaker

import (
	"sync"

	"github.com/zeromicro/go-zero/core/breaker"
)

/*
 +----------------------------------------------------------------------
 + Title        : BreakerManager
 + Author       : huwl
 + Version      : 1.0.0
 + Initial-Time : 2025-08-08
 + Last-time    : 这个文件最后修改的时间 + 修改人的名称
 + Desc         : 熔断管理器
 +----------------------------------------------------------------------
*/

var (
	manager *BreakerManager
	once    sync.Once
)

// 服务名称常量
const (
	UserService  = "user-service"
	GoodsService = "goods-service"
	OrderService = "order-service"
)

type BreakerManager struct {
	breakers map[string]breaker.Breaker
	mu       sync.RWMutex
}

/**
 * 获取熔断管理器
 *
 * @return *BreakerManager
 * @author huwl
 * @date 2025/11/04 12:42:36
 */
func GetBreakerManager() *BreakerManager {
	// 在你的熔断器管理器中使用 once.Do 是为了：
	// ✅ 线程安全：防止并发初始化导致的竞态条件
	// ✅ 唯一性保证：确保全局只有一个熔断器管理器实例
	// ✅ 高性能：后续调用几乎无开销
	// ✅ 代码简洁：比手动加锁更易读和维护
	// 这是 Go 语言中实现延迟初始化单例的最佳实践，特别适合在网关这种高并发场景下使用。
	once.Do(func() {
		manager = &BreakerManager{
			breakers: make(map[string]breaker.Breaker),
		}
	})

	return manager
}

// 获取或创建指定服务的熔断器
func (bm *BreakerManager) GetServiceBreaker(serviceName string) breaker.Breaker {
	bm.mu.RLock()
	brk, exists := bm.breakers[serviceName]
	bm.mu.RUnlock()

	if exists {
		return brk
	}

	bm.mu.Lock()
	defer bm.mu.Unlock()

	// 双重检查
	if brk, exists := bm.breakers[serviceName]; exists {
		return brk
	}

	brk = breaker.GetBreaker(serviceName)
	bm.breakers[serviceName] = brk
	return brk
}
